home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / adg_1_3.zip / DLG-DYNA.C < prev    next >
C/C++ Source or Header  |  1991-02-21  |  14KB  |  422 lines

  1. /****************************************************************************
  2. Module name: Dlg-Dyna.C
  3. Programmer : Jeffrey M. Richter.
  4. *****************************************************************************/
  5.  
  6. #include "..\nowindws.h"
  7. #undef NOCTLMGR
  8. #undef NOKERNEL
  9. #undef NOLSTRING
  10. #undef NOMEMMGR
  11. #undef NOUSER
  12. #undef NOWINMESSAGES
  13. #undef NOWINSTYLES
  14. #include <windows.h>
  15.  
  16. #include <memory.h>
  17.  
  18. #include "dlg-dyna.h"
  19.  
  20. typedef struct {
  21.    long dtStyle;
  22.    BYTE dtItemCount;
  23.    int  dtX;
  24.    int  dtY;
  25.    int  dtCX;
  26.    int  dtCY;
  27. // char dtMenuName[];      // Variable-length string.
  28. // char dtClassName[];     // Variable-length string.
  29. // char dtCaptionText[];   // Variable-length string.
  30. } DLGTEMPLATE, FAR *LPDLGTEMPLATE;
  31.  
  32. typedef struct {
  33.    short int PointSize;
  34. // char  szTypeFace[];     // Variable-length string.
  35. } FONTINFO, FAR *LPFONTINFO;
  36.  
  37. typedef struct {
  38.    int  dtilX;
  39.    int  dtilY;
  40.    int  dtilCX;
  41.    int  dtilCY;
  42.    int  dtilID;
  43.    long dtilStyle;
  44. // char dtilClass[];       // Variable-length string.
  45. // char dtilText[];        // Variable-length string.
  46. // BYTE dtilInfo;          // # of bytes in following memory block.
  47. // BYTE dtilData;          // Variable-length memory block.
  48. } DLGITEMTEMPLATE, FAR *LPDLGITEMTEMPLATE;
  49.  
  50.  
  51.  
  52. GLOBALHANDLE FAR PASCAL CreateDlgTemplate(
  53.    LONG dtStyle,
  54.    int dtX, int dtY,       // In dialog-box units
  55.    int dtCX, int dtCY,     // In dialog-box units
  56.    LPSTR dtMenuName,       // "" if no menu
  57.    LPSTR dtClassName,      // "" if standard dialog box class
  58.    LPSTR dtCaptionText, 
  59.    short int PointSize,    // Only used if DS_SETFONT style specified
  60.    LPSTR szTypeFace) {     // Only used if DS_SETFONT style specified
  61.  
  62.    GLOBALHANDLE hMem;
  63.    WORD wBlockLen, FAR *wNumBytes;
  64.    WORD wMenuNameLen, wClassNameLen, wCaptionTextLen, wTypeFaceLen;
  65.    LPSTR szDlgTemplate, szDlgTypeFace;
  66.    LPDLGTEMPLATE lpDlgTemplate;
  67.    LPFONTINFO lpFontInfo;
  68.  
  69.  
  70.    // Calculate number of bytes required by following fields:
  71.    wMenuNameLen     = 1 + lstrlen(dtMenuName);
  72.    wClassNameLen    = 1 + lstrlen(dtClassName);
  73.    wCaptionTextLen  = 1 + lstrlen(dtCaptionText);
  74.  
  75.    // Block must be large enough to contain the following:
  76.    wBlockLen =
  77.       sizeof(WORD) +          // Stores # of bytes used in block.
  78.       sizeof(DLGTEMPLATE) +   // # bytes for fixed part of DLGTEMPLATE.
  79.       wMenuNameLen +          // # bytes for menu name.
  80.       wClassNameLen +         // # bytes for dialog class name.
  81.       wCaptionTextLen;        // # bytes for dialog box caption.
  82.  
  83.  
  84.    if (dtStyle & DS_SETFONT) {
  85.       // Dialog box uses font other that System font.
  86.  
  87.       // Calculate # of bytes required for typeface name.
  88.       wTypeFaceLen = 1 + lstrlen(szTypeFace);
  89.  
  90.  
  91.       // Block must be large enough to include font information.
  92.       wBlockLen +=
  93.          sizeof(short int) +  // # bytes for font's point size.
  94.          wTypeFaceLen;        // # bytes for font typeface name.
  95.  
  96.    } else {
  97.       // Dialog box uses the System font.
  98.       wTypeFaceLen = 0;
  99.  
  100.       // Block length does not change.
  101.    }
  102.  
  103.  
  104.    // Allocate global block of memory for Dialog template.
  105.    hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, wBlockLen);
  106.    if (hMem == NULL) return(hMem);
  107.  
  108.  
  109.    // wNumBytes points to beginning of memory block.
  110.    wNumBytes = (WORD FAR *) GlobalLock(hMem);
  111.  
  112.    // Store in the first two bytes the number of bytes used in the block.
  113.    *wNumBytes = (WORD) wBlockLen;
  114.  
  115.  
  116.    // lpDlgTemplate points to start of DLGTEMPLATE in block.
  117.    lpDlgTemplate = (LPDLGTEMPLATE) (wNumBytes + 1);
  118.  
  119.    // Set the members of the DLGTEMPLATE structure.
  120.    lpDlgTemplate->dtStyle = dtStyle;
  121.    lpDlgTemplate->dtItemCount = 0;  // Incremented with calls to AddDlgItem.
  122.    lpDlgTemplate->dtX = dtX;
  123.    lpDlgTemplate->dtY = dtY;
  124.    lpDlgTemplate->dtCX = dtCX;
  125.    lpDlgTemplate->dtCY = dtCY;
  126.  
  127.  
  128.    // szDlgTemplate points to start of variable part of DLGTEMPLATE.
  129.    szDlgTemplate = (LPSTR) (lpDlgTemplate + 1);
  130.  
  131.    // Append the menu name, class name, and caption text to the block.
  132.    _fmemcpy(szDlgTemplate, dtMenuName, wMenuNameLen);
  133.    szDlgTemplate += wMenuNameLen;
  134.    _fmemcpy(szDlgTemplate, dtClassName, wClassNameLen);
  135.    szDlgTemplate += wClassNameLen;
  136.    _fmemcpy(szDlgTemplate, dtCaptionText, wCaptionTextLen);
  137.    szDlgTemplate += wCaptionTextLen;
  138.  
  139.  
  140.    if (dtStyle & DS_SETFONT) {
  141.       // Dialog box uses font other that System font.
  142.  
  143.       // lpFontInfo points to start of FONTINFO structure in block.
  144.       lpFontInfo = (LPFONTINFO) szDlgTemplate;
  145.  
  146.       // Set the members of the FONTINFO structure.
  147.       lpFontInfo->PointSize = PointSize;
  148.  
  149.       // szTypeFace points to start of variable part of FONTINFO.
  150.       szDlgTypeFace = (LPSTR) (lpFontInfo + 1);
  151.  
  152.       // Append the typeface name to the block.
  153.       _fmemcpy(szDlgTypeFace, szTypeFace, wTypeFaceLen);
  154.    }
  155.  
  156.    GlobalUnlock(hMem);
  157.    return(hMem);
  158. }
  159.  
  160.  
  161. // LOWORD = Success(TRUE)/Failure(FALSE), HIWORD=New hMem
  162. DWORD FAR PASCAL AddDlgControl (
  163.    GLOBALHANDLE hMem,      // Handle from CreateDlgData or AddDlgItem.
  164.    int dtilX, int dtilY,   // In dialog-box units.
  165.    int dtilCX, int dtilCY, // In dialog-box units.
  166.    int dtilID,       
  167.    long dtilStyle,         // WS_CHILD is automatically added.
  168.    LPSTR dtilClass,        // May be: "BUTTON",  "EDIT",      "STATIC",
  169.                            //         "LISTBOX", "SCROLLBAR", "COMBOBOX".
  170.    LPSTR dtilText,
  171.    BYTE dtilInfo,          // Number of additional data bytes.
  172.    LPBYTE dtilData) {      // Value passed through lpCreateParams field.
  173.                            // of CREATESTRUCT.
  174.  
  175.    GLOBALHANDLE hMemNew;
  176.    WORD wBlockLen, wClassLen, wTextLen, FAR *wNumBytes;
  177.    LPDLGTEMPLATE lpDlgTemplate;
  178.    LPDLGITEMTEMPLATE lpDlgItemTemplate;
  179.    LPSTR szDlgItemTemplate;
  180.  
  181.  
  182.    // Calculate number of bytes required by following fields:
  183.    wClassLen = 1 + lstrlen(dtilClass);
  184.    wTextLen  = 1 + lstrlen(dtilText);
  185.  
  186.  
  187.    // Block must be increased by to contain the following:
  188.    wBlockLen =
  189.       sizeof(DLGITEMTEMPLATE) +  // # bytes for fixed part of DLGITEMTEMPLATE.
  190.       wClassLen +                // # bytes for control class.
  191.       wTextLen +                 // # bytes for control text.
  192.       sizeof(BYTE) +             // 1 byte  for # of dtilInfo bytes (below).
  193.       dtilInfo;                  // # bytes for extra data.
  194.  
  195.  
  196.    // Guarantee that all controls have WS_CHILD style.
  197.    dtilStyle |= WS_CHILD;
  198.  
  199.    // Get number of bytes currently in the memory block.
  200.    wBlockLen += * (WORD FAR *) GlobalLock(hMem);
  201.    GlobalUnlock(hMem);
  202.  
  203.    // Increase the size of the memory block to include the new dialog item.
  204.    hMemNew = GlobalReAlloc(hMem, wBlockLen, GMEM_MOVEABLE | GMEM_ZEROINIT);
  205.    if (hMemNew == NULL)
  206.       return(MAKELONG(FALSE, hMem));
  207.  
  208.    // wNumBytes points to beginning of memory block.
  209.    wNumBytes = (WORD FAR *) GlobalLock(hMemNew);
  210.  
  211.  
  212.    // lpDlgTemplate points to start of DLGTEMPLATE in block.
  213.    lpDlgTemplate = (LPDLGTEMPLATE) (wNumBytes + 1);
  214.  
  215.    // Increment the number of controls in the template.
  216.    lpDlgTemplate->dtItemCount++;
  217.  
  218.  
  219.    // lpDlgItemTemplate points to start of new DLGITEMTEMPLATE in block.
  220.    // This is at the end of the memory block.
  221.    lpDlgItemTemplate = (LPDLGITEMTEMPLATE) (((LPSTR) wNumBytes) + *wNumBytes);
  222.  
  223.    // Set the members of the DLGITEMTEMPLATE structure.
  224.    lpDlgItemTemplate->dtilX = dtilX;
  225.    lpDlgItemTemplate->dtilY = dtilY;
  226.    lpDlgItemTemplate->dtilCX = dtilCX;
  227.    lpDlgItemTemplate->dtilCY = dtilCY;
  228.    lpDlgItemTemplate->dtilID = dtilID;
  229.    lpDlgItemTemplate->dtilStyle = dtilStyle;
  230.  
  231.  
  232.    // szDlgTemplate points to start of variable part of DLGITEMTEMPLATE.
  233.    szDlgItemTemplate = (LPSTR) (lpDlgItemTemplate + 1);
  234.  
  235.    // Append the control's class name, text to the block.
  236.    _fmemcpy(szDlgItemTemplate, dtilClass, wClassLen);
  237.    szDlgItemTemplate += wClassLen;
  238.    _fmemcpy(szDlgItemTemplate, dtilText, wTextLen);
  239.    szDlgItemTemplate += wTextLen;
  240.  
  241.    // Append the control's dtilInfo member.
  242.    *szDlgItemTemplate = dtilInfo;
  243.    szDlgItemTemplate += sizeof(BYTE);
  244.  
  245.    // Append the control's dtilData member.
  246.    _fmemcpy(szDlgItemTemplate, dtilData, dtilInfo);
  247.    szDlgItemTemplate += dtilInfo;
  248.  
  249.  
  250.    // Store in the first two bytes the number of bytes used in the block.
  251.    *wNumBytes = (WORD) (szDlgItemTemplate - (LPSTR) wNumBytes);
  252.  
  253.    GlobalUnlock(hMemNew);
  254.    return(MAKELONG(TRUE, hMemNew));
  255. }
  256.  
  257.  
  258.  
  259. void FAR PASCAL DoneAddingControls (GLOBALHANDLE hMem) {
  260.    WORD FAR *wNumBytes;
  261.  
  262.    // wNumBytes points to beginning of memory block.
  263.    wNumBytes = (WORD FAR *) GlobalLock(hMem);
  264.  
  265.    // Move all of the bytes in the block down two bytes.
  266.    _fmemcpy(wNumBytes, wNumBytes + 1, *wNumBytes - 2);
  267.    GlobalUnlock(hMem);
  268.  
  269.    // Once this function is executed, no more items can be 
  270.    // added to the dialog box template.
  271. }
  272.  
  273.  
  274.  
  275. #ifdef _DEMO
  276. //****************************************************************************
  277. // Functions for the Dynamic Modal and Modeless Dialog Box demonstrations.
  278.  
  279. #include "dialog.h"
  280.  
  281. #define MAXDLGITEMDATA  (10)
  282.  
  283. struct {
  284.    int x, y, cx, cy, id;
  285.    long Style;
  286.    LPSTR szClass, szText;
  287.    BYTE Info;
  288.    BYTE Data[MAXDLGITEMDATA];
  289.  
  290. } DynamicDlgBoxData[] = {
  291.  
  292.    {  4,  4, 32, 12, -1, SS_LEFT, "STATIC", "&Edit box:", 0, { 0 } },
  293.  
  294.    { 40,  4, 64, 12, ID_EDITBOX,
  295.       ES_LEFT | WS_BORDER | WS_TABSTOP | WS_GROUP, "EDIT", "", 0, { 0 } },
  296.  
  297.    {  4, 18, 40,  8, -1, SS_LEFT, "STATIC", "&Listbox:", 0, { 0 } },
  298.  
  299.    {  4, 28, 76, 41, ID_LISTBOX, LBS_NOTIFY | LBS_SORT | LBS_STANDARD |
  300.       WS_BORDER | WS_VSCROLL | WS_TABSTOP | WS_GROUP, "LISTBOX", "", 0, { 0 } },
  301.  
  302.    { 132,  4, 36, 12, IDOK, BS_DEFPUSHBUTTON | WS_TABSTOP | WS_GROUP,
  303.       "BUTTON", "&Ok", 0, { 0 } },
  304.  
  305.    { 176,  4, 36, 12, IDCANCEL, BS_PUSHBUTTON | WS_TABSTOP | WS_GROUP,
  306.       "BUTTON", "&Cancel", 0, { 0 } },
  307.  
  308.    {  88, 24, 56, 44, -1, BS_GROUPBOX | WS_GROUP, "BUTTON", "Group box", 0, { 0 } },
  309.  
  310.    { 92, 36, 48, 12, ID_RADIO1, BS_RADIOBUTTON | WS_TABSTOP,
  311.       "BUTTON", "Radio &1", 0, { 0 } },
  312.  
  313.    { 92, 48, 48, 12, ID_RADIO2, BS_RADIOBUTTON | WS_TABSTOP,
  314.       "BUTTON", "Radio &2", 0, { 0 } },
  315.  
  316.    { 152, 32, 60, 12, ID_CHECKBOX, BS_CHECKBOX | WS_TABSTOP | WS_GROUP,
  317.       "BUTTON", "C&heck box", 0, { 0 } },
  318.  
  319.    { 0, 0, 0, 0, 0, 0, NULL, NULL, 0, { 0 } }
  320. };
  321.  
  322.  
  323. BOOL FAR PASCAL DynamicDlgProc (HWND hDlg, WORD wMsg, WORD wParam, LONG lParam) {
  324.    BOOL fProcessed = TRUE;
  325.    switch (wMsg) {
  326.  
  327.       case WM_INITDIALOG:
  328.          break;
  329.  
  330.       case WM_COMMAND:
  331.          switch (wParam) {
  332.             case IDOK:
  333.             case IDCANCEL:
  334.                // Although the two push buttons for IDOK and IDCANCEL are
  335.                // not included in the modeless version of this dialog box,
  336.                // these options can still come through to here if the user
  337.                // presses the "Enter" or "Esc" keys respectively.
  338.  
  339.                // In the case of a modeless dialog box we cannot call the
  340.                // EndDialog() function.  We can determine if this window is
  341.                // the modeless one because it does not have the IDOK button
  342.                // within it.  In this case, GetDlgItem() below returns NULL.
  343.                if (GetDlgItem(hDlg, IDOK) == NULL)
  344.                   break;
  345.  
  346.                if (HIWORD(lParam) == BN_CLICKED)
  347.                   EndDialog(hDlg, wParam);
  348.                break;
  349.  
  350.             default:
  351.                break;
  352.          }
  353.          break;
  354.  
  355.       default:
  356.          fProcessed = FALSE; break;
  357.    }
  358.    return(fProcessed);
  359. }
  360.  
  361. GLOBALHANDLE FAR PASCAL BuildDynamicDlgBox (BOOL fModeless) {
  362.    GLOBALHANDLE hMem;
  363.    WORD x;
  364.    DWORD dwAddDlgControlResult;
  365.  
  366.    // Create the dynamic dialog box header information.
  367.     if (fModeless)
  368.        hMem = CreateDlgTemplate(
  369.           WS_BORDER | WS_CAPTION | WS_DLGFRAME |
  370.           WS_SYSMENU | WS_VISIBLE | WS_POPUP | DS_SETFONT,
  371.           6, 25, 216, 72, "", "", "Dynamic Modeless Demo", 8, "Helv");
  372.     else
  373.        hMem = CreateDlgTemplate(
  374.           WS_BORDER | WS_CAPTION | WS_DLGFRAME |
  375.           WS_SYSMENU | WS_VISIBLE | WS_POPUP,
  376.           6, 25, 216, 72, "", "", "Dynamic Modal Demo", 0, "");
  377.  
  378.  
  379.    if (hMem == NULL)
  380.       return(hMem);
  381.  
  382.    // Add each of the controls in the DynamicDlgBoxData array.
  383.    for (x = 0; DynamicDlgBoxData[x].szClass != NULL; x++) {
  384.  
  385.       // Do not add the "Ok" and "Cancel" buttons if a modeless dialog 
  386.       // box is being created.
  387.       if (fModeless) {
  388.          if (DynamicDlgBoxData[x].id == IDOK ||
  389.              DynamicDlgBoxData[x].id == IDCANCEL)
  390.             continue;
  391.       }
  392.  
  393.       dwAddDlgControlResult = AddDlgControl(hMem,
  394.          DynamicDlgBoxData[x].x,       DynamicDlgBoxData[x].y,
  395.          DynamicDlgBoxData[x].cx,      DynamicDlgBoxData[x].cy,
  396.          DynamicDlgBoxData[x].id,
  397.          DynamicDlgBoxData[x].Style | WS_VISIBLE,
  398.          DynamicDlgBoxData[x].szClass, DynamicDlgBoxData[x].szText,
  399.          DynamicDlgBoxData[x].Info,    DynamicDlgBoxData[x].Data);
  400.  
  401.       // LOWORD is FALSE if insufficient memory exists.
  402.       if (LOWORD(dwAddDlgControlResult) == FALSE) break;
  403.  
  404.       // HIWORD is handle to new block of memory.
  405.       hMem = HIWORD(dwAddDlgControlResult);
  406.    }
  407.  
  408.    // LOWORD is FALSE if insufficient memory exists, free what we have and
  409.    // return NULL to caller.
  410.    if (LOWORD(dwAddDlgControlResult) == FALSE) {
  411.       GlobalFree(hMem);
  412.       hMem = NULL;
  413.    } else {
  414.       // Cleanup the dialog box information.
  415.       DoneAddingControls(hMem);
  416.    }
  417.  
  418.    // Return the handle to the dynamic dialog box information.
  419.    return(hMem);
  420. }
  421. #endif
  422.